#pragma once

#include "Socket.hpp"
#include "Addr.hpp"
#include <memory>
#include <signal.h>
#include <unistd.h>
#include <functional>
#include <string>

using task_t = std::function<std::string(std::string &buffer)>;

class TcpServer
{
private:
    static void CustomIO(std::shared_ptr<Socket> _sockfd, Inet_Addr _Client, task_t task)
    {
        std::string _buffer;
        _sockfd->Recv(&_buffer);
        std::string ret = task(_buffer);
        _sockfd->Send(ret);

        _sockfd->Close();
    }

public:
    TcpServer(uint16_t port, task_t task)
        : _port(port), _listenSocket(std::make_unique<TcpSocket>()), _task(task)
    {
    }

    void Init()
    {
        _listenSocket->BulidSocket(_port);
    }

    void Start()
    {
        signal(SIGCHLD, SIG_IGN);
        while (1)
        {
            Inet_Addr _Client;
            std::shared_ptr<Socket> _sockfd = _listenSocket->Accept(&_Client);
            LOG(LogLevel::DEBUG) << "accept success" << "\r\n";

            if (fork() == 0)
            {
                _listenSocket->Close();
                CustomIO(_sockfd, _Client, _task);
                exit(0);
            }
            _sockfd->Close();
        }
    }

    ~TcpServer()
    {
    }

private:
    std::unique_ptr<Socket> _listenSocket;
    uint16_t _port;
    task_t _task;
};
